package com.heima.search.service.Impl;

import com.alibaba.fastjson.JSON;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.search.dto.ArticleDto;
import com.heima.model.search.dto.SearchDto;
import com.heima.model.search.pojo.ApUserSearch;
import com.heima.search.service.ApUSerSearchService;
import com.heima.search.service.SearchService;
import com.heima.utils.common.UserThreadLocal;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.util.QueryBuilder;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class SearchServiceImpl implements SearchService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private ApUSerSearchService apUserSearchService;
    /**
     * 文章搜素功能
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult<List<ArticleDto>> search( SearchDto dto) throws IOException {
        //保存搜索历史
        Integer userId = UserThreadLocal.getUserId();
        String searchWords = dto.getSearchWords();
        //判断是否为游客
        if (userId != 0) {
            //不是游客保存搜索历史
            ApUserSearch userSearch = new ApUserSearch();

            userSearch.setUserId(userId);
            userSearch.setKeyword(searchWords);
            userSearch.setCreatedTime(new Date());

            apUserSearchService.saveSearch(userSearch);
        }
        //创建搜素对象
        SearchRequest searchRequest = new SearchRequest("app_info_article");
        //构建BoolQueryBuilder对象组合查询条件
        BoolQueryBuilder boolqueryBuilder = new BoolQueryBuilder();
        //判断搜素条件是否为空
        if (StringUtils.isNotBlank(searchWords)) {
            //不为空则根据字段进行分词查询
            MultiMatchQueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(searchWords, "content", "title");
            boolqueryBuilder.must(queryBuilder);
        } else {
            //为空则查询全部
            MatchAllQueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
            boolqueryBuilder.must(queryBuilder);
        }
        //加入底部文章发布时间进行查询
        if (dto.getMinBehotTime().before(new Date())) {
            //发布时间小于当前时间
            RangeQueryBuilder queryBuilder = QueryBuilders.rangeQuery("publishTime").lt(dto.getMinBehotTime());
            boolqueryBuilder.must(queryBuilder);
        }
        searchRequest.source().query(boolqueryBuilder);
        //按照发布时间倒序
        searchRequest.source().sort("publishTime", SortOrder.DESC);
        //加入分页条件
        searchRequest.source().size(dto.getPageSize());
        //加入高亮字段
        HighlightBuilder highlightBuilder = new HighlightBuilder().field("title");
        highlightBuilder.preTags("<font style='color: red; font-size: inherit;'>");
        highlightBuilder.postTags("</font>");
        searchRequest.source().highlighter(highlightBuilder);
        //调用搜素方法进行查询,获取查询结果
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //解析查询结果
        SearchHits hits = response.getHits();
        SearchHit[] hitsHits = hits.getHits();
        List<ArticleDto> list = new ArrayList<>();
        for (SearchHit hitsHit : hitsHits) {
            String source = hitsHit.getSourceAsString();
            //解析source为对象
            ArticleDto articleDto = JSON.parseObject(source, ArticleDto.class);
            //处理高亮
            Map<String, HighlightField> highlightFields = hitsHit.getHighlightFields();
            if (highlightFields != null && highlightFields.size() > 0) {
                Text[] texts = highlightFields.get("title").getFragments();
                articleDto.setTitle(texts[0].toString());
            }
            //封装list集合中返回
            list.add(articleDto);
        }
        //响应结果
        return ResponseResult.okResult(list);
    }
}
